// Copyright 2017 Baidu Inc. All Rights Reserved.
// Author: Duan Lian (duanlian01@baidu.com)
//
// Description: OTA HTTP Downloader

#include "baidu_iot_ota_http_downloader.h"
#include <string.h>
#include "duer_log.h"
#include "heap_monitor.h"
#include "baidu_iot_ota_log.h"
#include "baidu_iot_ota_error.h"
#include "baidu_mbed_soc_wrapper.h"

namespace duer {

struct HttpClientCallbackContext {
    void* ctx;
    data_available_cb cb;
    OTAHttpDownloader* ota_http_downloader;
};

OTAHttpDownloader::OTAHttpDownloader(URL* url) {
    int url_str_len = 0;
    _p_http_client = NULL;

    if (url && url->valid()) {
        url_str_len = strlen(url->url()) + 1;
        _m_p_url = NEW(OTA) char[url_str_len];
        memmove(_m_p_url, url->url(), url_str_len);
    }
}

OTAHttpDownloader::~OTAHttpDownloader() {
    delete[] _m_p_url;
    _m_p_url = NULL;
}

int OTAHttpDownloader::connect() {
    _p_http_client = NEW(OTA) HttpClient();

    if (!_p_http_client) {
        DUER_LOGE("Http connect failed: no enough memory\n");

        return OTA_NO_ENOUGH_MEM;
    }

    return 0;
}
int OTAHttpDownloader::get(data_available_cb cb, void* ctx) {
    int ret = 0;

    if (!ctx) {
        DUER_LOGE("Argument invalid");

        return OTA_GET_DATA_FAILED;
    }

    HttpClientCallbackContext cb_ctx = {
        ctx,
        cb,
        this,
    };

    if (!_p_http_client) {
        DUER_LOGE("Http client not connected");

        return OTA_GET_DATA_FAILED;
    }

    _p_http_client->register_data_handler(&OTAHttpDownloader::data_available, &cb_ctx);
    ret = _p_http_client->get(_m_p_url, 0);

    return ret;
}

int OTAHttpDownloader::disconnect() {
    if (_p_http_client) {
        delete _p_http_client;
        _p_http_client = NULL;
    }

    DUER_LOGI("HTTP Disconnected!!!");

    return 0;
}

int OTAHttpDownloader::data_available(void* ctx, e_data_pos pos,
                                      const char* buf,
                                      size_t len,
                                      const char* type) {
    if (!ctx || !buf || !type) {
        return -1;
    }

    HttpClientCallbackContext* cb_ctx = (HttpClientCallbackContext*)ctx;

    OTA_FUNC_ENTER();
    DUER_LOGD("buf:%p, len:%d\n", buf, len);

    if (cb_ctx) {
        cb_ctx->cb((unsigned char*)buf, len, cb_ctx->ctx);
    }

    OTA_FUNC_LEAVE();

    return 0;
}

} // namespace duer
